#include <QThread>
#include <QCoreApplication>
#include <QMetaObject>
#include <fcntl.h>
#include <QTimer>

#include <QLibSsh/sshsftpconnection.h>
#include <QLibSsh/DelegateQThread.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 单线程调用
    {
        auto sftp1 = new SshSftpConnection(
            {
                .user = "shz",
                .host = "172.22.78.205",
                .port = 22,
                .password = "shz0905",
            }
        );
        sftp1->connectSftp();

        // 远程打开文件夹
        {
            auto dir = sftp1->OpenDir("./");
            if (!sftp1->DisplayDirContents(dir).empty()) {
                qDebug() << "OpenDir Test OK";
            }
        }

        // 远程创建文件夹
        {
            if (sftp1->CreateDir("./sftpTest", 0777)) {
                qDebug() << "CreateDir Test OK";
            }
        }

        // 远程重命名文件夹
        {
            if (sftp1->Rename("./sftpTest", "./sftpTest1")) {
                qDebug() << "RenameDir Test OK";
            }
        }

        // 远程删除文件夹
        {
            if (sftp1->RemoveDir("./sftpTest1")) {
                qDebug() << "RemoveDir Test OK";
            }
        }

        // 远程打开文件
        {
            if (!sftp1->OpenFile("/usr/bin/ssh", O_RDONLY).IsNull()) {
                qDebug() << "OpenFile Test OK";
            }
        }

        // 远程读取文件
        {
            auto file = sftp1->OpenFile("/usr/bin/ssh", O_RDONLY);
            auto buffer = sftp1->ReadFile(file);
            if (buffer.length() > 0) {
                qDebug() << "ReadFile Test OK";
            }
        }

        // 远程写入文件
        {
            auto file = sftp1->OpenFile("/usr/bin/ssh", O_RDONLY);
            auto buffer = sftp1->ReadFile(file);
            file = sftp1->OpenFile("./sshcopy", O_WRONLY | O_CREAT, 0777);
            if (sftp1->WriteFile(file, buffer)) {
                qDebug() << "WriteFile Test OK";
            } else {
                qDebug() << "WriteFile Test FAIL";
            }
        }

        // 远程创建软链接
        {
            if (sftp1->SoftLink("./sshcopy", "./sftpTestSoftLink")) {
                qDebug() << "SoftLink Test OK";
            } else {
                qDebug() << "SoftLink Test FAIL";
            }
        }

        // 远程创建硬链接
        {
            if (sftp1->HardLink("./sshcopy", "./sftpTestHardLink")) {
                qDebug() << "HardLink Test OK";
            } else {
                qDebug() << "HardLink Test FAIL";
            }
        }

        // 远程读取链接
        {
            if (const auto path = sftp1->ReadLink("./sftpTestSoftLink"); path != nullptr) {
                qDebug() << "ReadLink Soft Test OK";
            } else {
                qDebug() << "ReadLink Soft Test FAIL";
            }

            if (const auto path = sftp1->ReadLink("./sftpTestSoftLink"); path != nullptr) {
                qDebug() << "ReadLink Hard Test OK";
            } else {
                qDebug() << "ReadLink Hard Test FAIL";
            }
        }

        // 远程清除链接
        {
            if (sftp1->Unlink("./sftpTestSoftLink")) {
                qDebug() << "Unlink Soft Test OK";
            } else {
                qDebug() << "Unlink Soft Test FAIL";
            }

            if (sftp1->Unlink("./sftpTestHardLink")) {
                qDebug() << "Unlink Hard Test OK";
            } else {
                qDebug() << "Unlink Hard Test FAIL";
            }
        }

        // 远程重命名文件
        {
            if (sftp1->Rename("./sshcopy", "./sshcopyDelete")) {
                qDebug() << "RenameFile Test OK";
            }
        }

        // 远程删除文件
        {
            if (sftp1->RemoveFile("./sshcopyDelete")) {
                qDebug() << "RemoveFile Test OK";
            }
        }
        sftp1->deleteLater();
    }

    // 多线程调用
    {
        auto sftp2 = new SshSftpConnection(
            {
                .user = "shz",
                .host = "172.22.78.205",
                .port = 22,
                .password = "shz0905",
            }, &a
        );
        qDebug() << "Main Thread, " << QThread::currentThreadId();
        auto delegateQThread = new DelegateQThread(&a);
        sftp2->moveToThread(delegateQThread);
        SshSftpConnection::SftpDir dir {nullptr};
        delegateQThread->Enqueue(&SshSftpConnection::connectSftp, std::ref(sftp2));

        // 远程打开文件夹
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp, SshSftpConnection::SftpDir& dir) {
                dir = sftp->OpenDir("./");}, std::ref(sftp2), std::ref(dir));
            delegateQThread->Enqueue([](SshSftpConnection* sftp, SshSftpConnection::SftpDir& dir) {
                if (!sftp->DisplayDirContents(dir).empty()) {
                    qDebug() << "OpenDir Test OK";
                }

            }, std::ref(sftp2), std::ref(dir));
        }

        // 远程创建文件夹
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->CreateDir("./sftpTest", 0777)) {
                    qDebug() << "CreateDir Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程重命名文件夹
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->Rename("./sftpTest", "./sftpTest1")) {
                    qDebug() << "RenameDir Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程删除文件夹
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->RemoveDir("./sftpTest1")) {
                    qDebug() << "RemoveDir Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程打开文件
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (!sftp->OpenFile("/usr/bin/ssh", O_RDONLY).IsNull()) {
                    qDebug() << "OpenFile Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程读取文件
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                auto file = sftp->OpenFile("/usr/bin/ssh", O_RDONLY);
                auto buffer = sftp->ReadFile(file);
                if (buffer.length() > 0) {
                    qDebug() << "ReadFile Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程写入文件
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                auto file = sftp->OpenFile("/usr/bin/ssh", O_RDONLY);
                auto buffer = sftp->ReadFile(file);
                file = sftp->OpenFile("./sshcopy", O_WRONLY | O_CREAT, 0777);
                if (sftp->WriteFile(file, buffer)) {
                    qDebug() << "WriteFile Test OK";
                } else {
                    qDebug() << "WriteFile Test FAIL";
                }
            }, std::ref(sftp2));
        }

        // 远程创建软链接
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->SoftLink("./sshcopy", "./sftpTestSoftLink")) {
                    qDebug() << "SoftLink Test OK";
                } else {
                    qDebug() << "SoftLink Test FAIL";
                }
            }, std::ref(sftp2));
        }

        // 远程创建硬链接
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->HardLink("./sshcopy", "./sftpTestHardLink")) {
                    qDebug() << "HardLink Test OK";
                } else {
                    qDebug() << "HardLink Test FAIL";
                }
            }, std::ref(sftp2));
        }

        // 远程读取链接
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (const auto path = sftp->ReadLink("./sftpTestSoftLink"); path != nullptr) {
                    qDebug() << "ReadLink Soft Test OK";
                } else {
                    qDebug() << "ReadLink Soft Test FAIL";
                }

                if (const auto path = sftp->ReadLink("./sftpTestSoftLink"); path != nullptr) {
                    qDebug() << "ReadLink Hard Test OK";
                } else {
                    qDebug() << "ReadLink Hard Test FAIL";
                }
            }, std::ref(sftp2));
        }

        // 远程清除链接
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->Unlink("./sftpTestSoftLink")) {
                    qDebug() << "Unlink Soft Test OK";
                } else {
                    qDebug() << "Unlink Soft Test FAIL";
                }

                if (sftp->Unlink("./sftpTestHardLink")) {
                    qDebug() << "Unlink Hard Test OK";
                } else {
                    qDebug() << "Unlink Hard Test FAIL";
                }
            }, std::ref(sftp2));
        }

        // 远程重命名文件
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->Rename("./sshcopy", "./sshcopyDelete")) {
                    qDebug() << "RenameFile Test OK";
                }
            }, std::ref(sftp2));
        }

        // 远程删除文件
        {
            delegateQThread->Enqueue([](SshSftpConnection* sftp) {
                if (sftp->RemoveFile("./sshcopyDelete")) {
                    qDebug() << "RemoveFile Test OK";
                }
            }, std::ref(sftp2));
        }

        QTimer::singleShot(3000, [&] {
            QObject::connect(delegateQThread, &QThread::finished, delegateQThread, [&] () {
                qDebug() << "QTimer::singleShot Thread, " << QThread::currentThreadId();
            });
            QObject::connect(delegateQThread, &QThread::finished, delegateQThread, &QObject::deleteLater);
            QObject::connect(delegateQThread, &QThread::finished, &a, &QCoreApplication::quit);
            delegateQThread->Stop();
        });
    }

    return a.exec();
}

